package com.example.androidmaps;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.example.androidmaps.Login.CheckCloudUsernamePassword;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.apache.ApacheHttpTransport;

public class MainActivity extends FragmentActivity  {
	private Database db; 
	private GoogleMap mapView;
	private int CloudId = 0;
	private boolean inSatellite = false;
	private AlertDialog.Builder dlgAlert;
	private Map<Double, String> pointNames = new HashMap<Double, String>();
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		db = new Database(this);
		dlgAlert  = new AlertDialog.Builder(this);
		//db.open();
		//db.LogOutUser();
		android.support.v4.app.Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.mapView);
        SupportMapFragment mapFragment = (SupportMapFragment)fragment;
        mapView = mapFragment.getMap();
        LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
        Criteria criteria = new Criteria();
        String provider = service.getBestProvider(criteria, false);
        Location location = service.getLastKnownLocation(provider);
        LatLng userLocation = new LatLng(location.getLatitude(),location.getLongitude());
        CameraUpdate center=CameraUpdateFactory.newLatLng(userLocation);
        CameraUpdate zoom = CameraUpdateFactory.zoomTo(15);
        mapView.addMarker(new MarkerOptions()
        	.position(userLocation)
        	.title("Your Locations!"));
        mapView.moveCamera(center);
        mapView.animateCamera(zoom);
        UpdateCurrentLocation task3 = new UpdateCurrentLocation();
		task3.execute((double)CloudId, location.getLongitude(), location.getLatitude());
		
		GetNearbyLocaitons task4 = new GetNearbyLocaitons();
		task4.execute(location.getLongitude(), location.getLatitude());
		JSONObject places = null;
		try {
			places = task4.get();
		}
		catch (Exception e) {
			places = null;//vicinity, name, geometry:location:lng lat 
		}
		if(places != null){
			Iterator<String> iter;
			JSONArray arr = null;
			try {
				arr = places.getJSONArray("results");
				for(int i = 0; i < arr.length(); i++){
					JSONObject row = arr.getJSONObject(i);
					final String add = row.getString("vicinity");
					final String name = row.getString("name");
					JSONObject geo = row.getJSONObject("geometry");
					JSONObject loc = geo.getJSONObject("location");
					final double lon = loc.getDouble("lng");
					final double lat = loc.getDouble("lat");
					pointNames.put(lon, name + " " + add);
	                LatLng searchLocation = new LatLng(lat,lon);
	                mapView.addMarker(new MarkerOptions()
	            	.position(searchLocation)
	            	.title(name + " " + add));
		            mapView.setOnMapLongClickListener(new OnMapLongClickListener() {
		                @Override
		                public void onMapLongClick(LatLng p_point) {
		                	final String name = (String)pointNames.get(p_point.longitude);
		                	final double lon = p_point.longitude;
		                	final double lat = p_point.latitude;
		            		dlgAlert.setMessage("Would you like to save this location as a favorite?");
		            		dlgAlert.setTitle("Save Location?");
		            		dlgAlert.setPositiveButton("Save",
		            			    new DialogInterface.OnClickListener() {
		            			        public void onClick(DialogInterface dialog, int which) {
		            			        	InsertFavoritePlace task = new InsertFavoritePlace();
		            			    		task.execute(((Integer)CloudId).toString(), ((Double)lon).toString(), ((Double)lat).toString(), name);
		            			    		int check = -1;
		            			    		try {
		            			    			check = task.get();
		            			    		}
		            			    		catch (Exception e) {
		            			    			check = -1;
		            			    		}
		            			        }
		            			    });
		            		dlgAlert.setCancelable(true);
		                	MainActivity.this.runOnUiThread(new Runnable() {

		    			        public void run() {
		    			        	try{
		    			        		dlgAlert.create().show();
		    			        	}
		    			        	catch(Exception e){
		    			        		//something happened with the dialog, oh well
		    			        	}

		    			        }
		    			    });
		                }
		            });
				}
			} catch (JSONException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
		}
	}
	
	public void SearchLocation(View v){
		String address = ((EditText)findViewById(R.id.SearchText)).getText().toString();
		Geocoder geoCoder = new Geocoder(this, Locale.getDefault());    
        try {
            final List<Address> addresses = geoCoder.getFromLocationName(address, 5);
            String add = "";
            if (addresses.size() > 0) {
            	CameraUpdate zoom = CameraUpdateFactory.zoomTo(15);
                LatLng searchLocation = new LatLng(addresses.get(0).getLatitude(),addresses.get(0).getLongitude());
                CameraUpdate center=CameraUpdateFactory.newLatLng(searchLocation);
                mapView.addMarker(new MarkerOptions()
            	.position(searchLocation)
            	.title(addresses.get(0).getAddressLine(0) + " " + addresses.get(0).getAddressLine(1)));
	            mapView.moveCamera(center);
	            mapView.animateCamera(zoom);
	            mapView.setOnMapLongClickListener(new OnMapLongClickListener() {
	                @Override
	                public void onMapLongClick(LatLng p_point) {
	                	
	            		dlgAlert.setMessage("Would you like to save this location as a favorite?");
	            		dlgAlert.setTitle("Save Location?");
	            		dlgAlert.setPositiveButton("Save",
	            			    new DialogInterface.OnClickListener() {
	            			        public void onClick(DialogInterface dialog, int which) {
	            			        	InsertFavoritePlace task = new InsertFavoritePlace();
	            			    		task.execute(((Integer)CloudId).toString(), ((Double)addresses.get(0).getLongitude()).toString(), ((Double)addresses.get(0).getLatitude()).toString(), addresses.get(0).getAddressLine(0) + " " + addresses.get(0).getAddressLine(1));
	            			    		int check = -1;
	            			    		try {
	            			    			check = task.get();
	            			    		}
	            			    		catch (Exception e) {
	            			    			check = -1;
	            			    		}
	            			        }
	            			    });
	            		dlgAlert.setCancelable(true);
	                	MainActivity.this.runOnUiThread(new Runnable() {

	    			        public void run() {
	    			        	try{
	    			        		dlgAlert.create().show();
	    			        	}
	    			        	catch(Exception e){
	    			        		//something happened with the dialog, oh well
	    			        	}

	    			        }
	    			    });
	                }
	            });
            }  
    } catch (IOException e) {

            e.printStackTrace();
        }
	}
	
	public void SwitchView(View v){
		if(inSatellite){
			mapView.setMapType(GoogleMap.MAP_TYPE_NORMAL);
			((Button)findViewById(R.id.ChangeViewButton)).setText("Normal View");
			inSatellite = false;
		}
		else{
			mapView.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
			((Button)findViewById(R.id.ChangeViewButton)).setText("Satellite View");
			inSatellite = true;
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	public void toFriends(){
		Intent goToFriends = new Intent(MainActivity.this,Friends.class);
    	startActivity(goToFriends);
	}
	
	public void toPlaces(){
		Intent goToPlaces = new Intent(MainActivity.this,FavoritePlaces.class);
    	startActivity(goToPlaces);
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
	    // Handle item selection
	    switch (item.getItemId()) {
	        case R.id.action_settings:
	            //do settings stuff?
	        	return true;
	        case R.id.logout://logout current user
	            db.LogOutUser();
	            Intent intent = new Intent(MainActivity.this,Login.class);
            	startActivity(intent);
	            return true;
	        case R.id.toFriends:
	            toFriends();
	            return true;
	        case R.id.toPlaces:
	            toPlaces();
	            return true;
	        default:
	            return super.onOptionsItemSelected(item);
	    }
	}
	
	@Override
	public void onPause() {
	    super.onPause();
	}
	
	
	@Override
	public void onResume() {
		/// see if any user is logged in, the perform an action in the ProcessUserLoggedIn method
	    super.onResume();
	    new CheckUserLoggedIn().execute();
	}
	
	/*
	 * This method will be called once the database has checked if a user is logged in.
	 * If no user is logged in, null will be returned and we want to redirect the user to the 
	 * login page.
	 */
	public void ProcessUserLoggedIn(User user){
		if(user == null){
			//redirect to login page here
			Intent loginIntent = new Intent(MainActivity.this,Login.class);
	    	startActivity(loginIntent);
		}
		else{
			//Do something here, we know user is logged in
			CloudId = user.CloudId;
		}
	}
	
	
	/*
	 * |||||||||||||||||||||||||||||||||||
	 * Async Methods Go Here
	 * |||||||||||||||||||||||||||||||||||
	 */
	
	public class CheckUserLoggedIn extends AsyncTask<Void, Void, User> {
		// perform the database access
		User user;
		
		@Override
		protected User doInBackground(Void... params) {
			db.open();
			// call database and return user, if null, no user logged in
			user = db.CheckUserLoggedIn();
			return user;
		} // end method doInBackground
		
		@Override
		protected void onPostExecute(User user)
		{
			ProcessUserLoggedIn(user);
		} // end method onPostExecute

	}
	
	public class UpdateCurrentLocation extends AsyncTask<Double, Void, Void> {
		@Override
		protected Void doInBackground(Double... params) {
			new CloudHelper().UpdateCurrentLocation(params[0], params[1], params[2]);
			return null;
		}
	}
	
	public class InsertFavoritePlace extends AsyncTask<String, Void, Integer> {
		@Override
		protected Integer doInBackground(String... params) {
			return new CloudHelper().InsertFavoritePlace(params[0], params[1],params[2], params[3]);
		}
	}
	
	public class GetNearbyLocaitons extends AsyncTask<Double, Void, JSONObject> {
		//https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=AIzaSyA712jyN6NY0VXSGf8zgXfXSRhq01O8RLY"
	    InputStream is = null;
	    JSONObject jObj = null;
	    String json = "";
	    String url1 = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=";
	    String url2 = "&radius=2500&types=bar&sensor=false&key=AIzaSyDXr6A7afxLcxMWCwYnt_UI0NLwMU8tJvU";
	    double lon = 0;
	    double lat = 0;
	    private static final String keyString = "AIzaSyAgXrlnCMmHq46mp5TYfmV1ywT0ogMrtyU";


	@Override
	protected JSONObject doInBackground(Double... params) {
		lon = params[0];
		lat = params[1];
	    // defaultHttpClient
	    DefaultHttpClient httpClient = new DefaultHttpClient();
	    HttpPost httpPost = new HttpPost(getUrl());

	    HttpResponse httpResponse = null;
	    try {
	        httpResponse = httpClient.execute(httpPost);
	    } catch (ClientProtocolException e2) {
	        // TODO Auto-generated catch block
	        e2.printStackTrace();
	    } catch (IOException e2) {
	        // TODO Auto-generated catch block
	        e2.printStackTrace();
	    }
	    HttpEntity httpEntity = httpResponse.getEntity();
	    try {
	        is = httpEntity.getContent();
	    } catch (IllegalStateException e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
	    } catch (IOException e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
	    }

	    BufferedReader reader = null;
	    try {
	        reader = new BufferedReader(
	                new InputStreamReader(is, "iso-8859-1"), 8);
	    } catch (UnsupportedEncodingException e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
	    }
	    StringBuilder sb = new StringBuilder();
	    String line = null;
	    try {
	        while ((line = reader.readLine()) != null) {
	            sb.append(line + "\n");
	        }
	    } catch (IOException e1) {
	        // TODO Auto-generated catch block
	        e1.printStackTrace();
	    }
	    try {
	        is.close();
	    } catch (IOException e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
	    }
	    json = sb.toString();

	    try {
	        jObj = new JSONObject(json);
	    } catch (JSONException e) {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
	    }

	    // return JSON String
	    return jObj;
	}

		public String getUrl() {
		    return url1 + lat + "," + lon + url2;
		}
	}

}
